/*
 * Copyright © 2004-2014 chenYuan. All rights reserved.
 * @Website:wwww.jspx.net
 * @Mail:39793751@qq.com
 * @author: chenYuan , 陈原
 * @License: Jspx.net Framework Code is open source (LGPL)，Jspx.net Framework 使用LGPL 开源授权协议发布。
 * @jvm:jdk1.6+  x86/amd64
 *
 */
package com.jspx.txweb.view;


import com.jspx.boot.EnvFactory;
import org.slf4j.Logger;
import com.jspx.boot.environment.Environment;
import com.jspx.boot.environment.EnvironmentTemplate;
import org.slf4j.LoggerFactory;
import com.jspx.txweb.annotation.HttpMethod;
import com.jspx.txweb.support.ActionSupport;
import com.jspx.utils.DateUtil;
import com.jspx.utils.NumberUtil;
import com.jspx.utils.StringUtil;

import java.io.File;
import java.util.Date;

/**
 * Created with IntelliJ IDEA.
 * User: chenYuan
 * Date: 12-5-25
 * Time: 下午4:36
 * 参数说明：
 * String MerId - 商户号，长度为15个字节的数字串，由ChinaPay或清算银行分配。
 * String OrdId - 订单号，长度为16个字节的数字串，由商户系统生成，失败的订单号允许重复支付。
 * String TransAmt - 交易金额，长度为12个字节的数字串，例如：数字串"000000001234"表示12.34元。
 * String CuryId - 货币代码, 长度为3个字节的数字串，目前只支持人民币，取值为"156" 。
 * String TransDate - 交易日期，长度为8个字节的数字串，表示格式为：YYYYMMDD。
 * String TransType - 交易类型，长度为4个字节的数字串，取值范围为："0001"和"0002"， 其中"0001"表示消费交易
 * 返回值：
 * String CheckValue[256] - 即NetPayClient根据上述输入参数生成的商户数字签名，长度为256字节的字符串。
 */
@HttpMethod(caption = "银联支付接口")
public class ChinaPayView extends ActionSupport {
    private static final Logger log = LoggerFactory.getLogger(ChinaPayView.class);
    public static final String payType = "ChinaPay";
    private EnvironmentTemplate environmentTemplate = EnvFactory.getEnvironmentTemplate();
    private String keyFileFolder = environmentTemplate.getString(Environment.webInfPath) + "chinapay/keys/";//"D:/website/www/root/WEB-INF/chinapay/keys/";
    private long orderId = 0;
    private String payOrderId = StringUtil.empty;
    //交易金额，长度为12个字节的数字串，例如：数字串"000000001234"表示12.34元。
    private String transAmt = "00";
    //货币代码, 长度为3个字节的数字串，目前只支持人民币，取值为"156" 。
    private String currencyId = "156";
    //交易日期，长度为8个字节的数字串，表示格式为：YYYYMMDD。
    private String transDate = DateUtil.toString(new Date(), "yyyyMMdd");
    //String TransType - 交易类型，长度为4个字节的数字串，取值范围为："0001"和"0002"， 其中"0001"表示消费交易
    //其中"0001"表示消费交易，"0002"表示退货交易
    private String transType = "0001";
    //银联商户号
    private String merId = StringUtil.empty;
    //银联网关号,不填都可以
    private String gateId = StringUtil.empty;

    //备注信息
    private String priv1 = StringUtil.empty;
    //版本号，不能错
    private String version = "20040916";
    //金额
    private float floatTransAmt = 0;

    public ChinaPayView() {

    }


    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getGateId() {
        return gateId;
    }

    public void setGateId(String gateId) {
        this.gateId = gateId;
    }

    public String getPriv1() {
        return priv1;
    }

    public void setPriv1(String priv1) {
        this.priv1 = priv1;
    }

    public String getTransAmt() {
        return transAmt;
    }

    public void setTransAmt(String transAmt) {
        this.transAmt = transAmt;
    }

    public void setTransAmt(float floatTransAmt) {
        this.floatTransAmt = floatTransAmt;
        this.transAmt = getPayTransAmt();
    }

    public float getFloatTransAmt() {
        return floatTransAmt;
    }

    public String getCurrencyId() {
        return currencyId;
    }

    public void setCurrencyId(String currencyId) {
        this.currencyId = currencyId;
    }

    public String getTransDate() {
        return transDate;
    }

    public void setTransDate(Date transDate) {
        this.transDate = DateUtil.toString(transDate, "yyyyMMdd");
    }

    public String getTransType() {
        return transType;
    }

    public void setTransType(String transType) {
        this.transType = transType;
    }

    public String getMerId() {
        return merId;
    }

    public void setMerId(String merId) {
        this.merId = merId;
    }

    public String getKeyFileFolder() {
        return keyFileFolder;
    }

    public void setKeyFileFolder(String keyFileFolder) {
        this.keyFileFolder = keyFileFolder;
    }

    public long getOrderId() {
        return orderId;
    }

    public void setOrderId(long orderId) {
        this.orderId = orderId;
        this.payOrderId = getPayOrderId();
    }

    /**
     * //16位本地订单号转为银联订单号 , 银联订单号 5-9 为商户 后几位编号
     *
     * @return 银联订单号
     */
    public String getPayOrderId() {

        if (merId == null || merId.length() < 11) return StringUtil.empty;
        String payId = "0000000000000000" + orderId;
        payId = payId.substring(payId.length() - 16, payId.length());
        return payId.substring(0, 4) + merId.substring(10, merId.length()) + payId.substring(9, payId.length());
    }

    public String getPayTransAmt() {
        //12长度
        String chinaPayNum = NumberUtil.toString(NumberUtil.getRound(floatTransAmt, 2));
        int dot = chinaPayNum.indexOf(".");
        if (dot == -1)
            chinaPayNum = chinaPayNum + "00";
        else {
            String end = StringUtil.substringAfter(chinaPayNum, ".");
            chinaPayNum = chinaPayNum.substring(0, dot) + (end + "000").substring(0, 2);
        }
        chinaPayNum = "0000000000000" + chinaPayNum;
        return chinaPayNum.substring(chinaPayNum.length() - 12, chinaPayNum.length());
    }

    /**
     * key在目录里边保存的格式
     * MerPrK_808080233500333_20120425113801.key
     *
     * @return 得到私密文件
     */
    private File getMerPrKFile() {
        File file = new File(keyFileFolder);
        for (File f : file.listFiles()) {
            if (merId.equals(StringUtil.substringBetween(f.getName(), "_", "_")) && f.getName().endsWith(".key") && f.getName().toLowerCase().startsWith("merprk_")) {
                return f;
            }
        }
        return null;
    }

    /**
     * key在目录里边保存的格式
     * PgPubk_808080233500333_20120425113801.key
     *
     * @return 得到公密文件
     */
    private File getPgPubkFile() {
        File file = new File(keyFileFolder);
        for (File f : file.listFiles()) {
            if (merId.equals(StringUtil.substringBetween(f.getName(), "_", "_")) && f.getName().endsWith(".key") && f.getName().toLowerCase().startsWith("pgpubk_")) {
                return f;
            }
        }
        return null;
    }

    /**
     * @return 获得对应商户的签名数据。
     */
    public String getChkValue() {
        File file = getMerPrKFile();
        chinapay.PrivateKey key = new chinapay.PrivateKey();
        if (key.buildKey(merId, 0, file.getAbsolutePath())) {
            chinapay.SecureLink sl = new chinapay.SecureLink(key);
            return sl.signOrder(merId, getPayOrderId(), getPayTransAmt(), getCurrencyId(), getTransDate(), getTransType());
        }
        log.error("商户的签名生成失败,merId=" + merId);
        return StringUtil.empty;
    }

    /**
     * <input type=hidden name="BgRetUrl" value="http://${businessCard.namespace}/share/chinapayback1.do?id=${chinapay.orderId}">
     * <input type=hidden name="PageRetUrl" value="http://${businessCard.namespace}/share/chinapayback2.do?id=${chinapay.orderId}">
     *
     * @return 得到HTML变量  BgRetUrl  PageRetUrl 不在生成范围
     */
    public String getVarInputs()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("<input type=hidden name=\"MerId\" value=\"").append(merId).append("\" >");
        sb.append("<input type=hidden name=\"OrdId\" value=\"").append(getPayOrderId()).append("\" >");
        sb.append("<input type=hidden name=\"TransAmt\" value=\"").append(getPayTransAmt()).append("\" >");
        sb.append("<input type=hidden name=\"CuryId\" value=\"").append(currencyId).append("\" >");
        sb.append("<input type=hidden name=\"TransDate\" value=\"").append(getTransDate()).append("\" >");
        sb.append("<input type=hidden name=\"TransType\" value=\"").append(getTransType()).append("\" >");
        sb.append("<input type=hidden name=\"Version\" value=\"").append(version).append("\" >");
        sb.append("<input type=hidden name=\"GateId\" value=\"").append(gateId).append("\" >");
        sb.append("<input type=hidden name=\"Priv1\" value=\"").append(priv1).append("\" >");
        sb.append("<input type=hidden name=\"ChkValue\" value=\"").append(getChkValue()).append("\" >");
        return sb.toString();
    }

    /**
     * @return 交易返回结果验证, 交易成功，一般验证成功后保存保存日志记录
     */
    public boolean getVerifyTransResponse() {

        merId = getString("merid");
        if (StringUtil.isNULL(merId)) return false;
        transDate = getString("transdate");
        payOrderId = getString("orderno");
        transType = getString("transtype");
        transAmt = getString("amount");
        currencyId = getString("currencycode");
        String orderStatus = getString("status");
        String chkValue = getString("checkvalue");
        chinapay.PrivateKey key = new chinapay.PrivateKey();
        File file = getPgPubkFile();
        if (file == null || !file.isFile()) {
            log.info("交易验证公密key读取失败,merId=" + merId);
            return false;
        }
        boolean flag = key.buildKey("999999999999999", 0, file.getAbsolutePath());
        if (!flag) {
            log.info("交易验证key失败,merId=" + merId);
            return false;
        }
        chinapay.SecureLink sl = new chinapay.SecureLink(key);
        return sl.verifyTransResponse(merId, payOrderId, transAmt, currencyId, transDate, transType, orderStatus, chkValue);
    }

    public String getResponsePayOrderId() {
        return payOrderId;
    }

    public static void main(String args[]) throws Exception {
        String TransType = "0001";
        String merId = "808080233500333";
        ChinaPayView chinaPayAdapter = new ChinaPayView();
        chinaPayAdapter.setMerId(merId);
        chinaPayAdapter.setOrderId(12);

        log.debug("----" + chinaPayAdapter.getKeyFileFolder());

        log.debug(chinaPayAdapter.getOrderId() + ":订单号:" + chinaPayAdapter.getPayOrderId());
        chinaPayAdapter.setTransAmt(0.01f);
        chinaPayAdapter.setTransDate(new Date());
        chinaPayAdapter.setTransType(TransType);
        log.debug(chinaPayAdapter.getOrderId() + ":订单号:" + chinaPayAdapter.getPayOrderId());
        log.debug("html:" + chinaPayAdapter.getVarInputs());

        //-------------------------
        if (chinaPayAdapter.getVerifyTransResponse()) {
            log.debug("交易成功");
        } else
            log.debug("交易失败");

        log.debug(chinaPayAdapter.getTransAmt());

    }
}